home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / lang / c--c0202 / pcx.h-- < prev    next >
Encoding:
Text File  |  1994-04-22  |  10.4 KB  |  366 lines

  1. /*
  2.     SPHINX Programming (C) 1994.
  3.     NAME:  PCX.H--
  4.     DESCRIPTION:  This file contains a collection of procedures for reading
  5.                   PCX format of graphics files.
  6.                   Current support is limited to 256 color PCX's which are
  7.                   320x200 or smaller.
  8.     LAST MODIFIED:  22 Apr 1994
  9.     PROCEDURES DEFINED IN THIS FILE:
  10.     byte readPCX(filename,bufseg,bufoffset,bufsize,buftype)
  11.     byte readPCXpalette(filename,palsegment,paloffset)
  12.         byte savePCX(filename,bufseg,bufoffset,xsize,ysize,palseg,paloffset)
  13. */
  14.  
  15.  
  16.  
  17. // error codes
  18. enum {  pcx_e_ok,        // no errors, everything OK
  19.         pcx_e_nofile,    // file could not be openned
  20.         pcx_e_noinput,   // unable to read enough data from input file
  21.         pcx_e_nooutput,  // unable to write enough data to output file
  22.         pcx_e_badheader, // PCX header was invalid
  23.         pcx_e_not256,    // PCX file is not 256 colours
  24.         pcx_e_toobig,    // PCX file is too big for given buffer
  25.         pcx_e_error      // some other error occurred
  26.      };
  27.  
  28. // buffer types
  29. enum { pcx_raw,      // just raw data (no x and y sizes)
  30.        pcx_cut       // cut buffer format (includes x and y sizes)
  31.      };
  32.  
  33.  
  34. ?align   // make sure we start off word aligned, so the buffer is contiguous
  35. // PCX header (128 bytes).
  36. ?define PCX_HEADERSIZE 128
  37. ?define PCXBUFSIZE 1024     // input file read buffer size
  38. byte PCX_manufacturer;      // manufacturer byte (always 0A0h)
  39. byte PCX_version;           // pcx Version
  40. byte PCX_encoding;          // (always 1)
  41. byte PCX_bits_per_pixel;    // color bits per pixel
  42. word PCX_xmin;              // image origin x
  43. word PCX_ymin;              // image origin y
  44. word PCX_xmax;              // image end x
  45. word PCX_ymax;              // image end y
  46. word PCX_hres;              // horizontal resolution
  47. word PCX_vres;              // vertical resolution
  48. byte PCX_palette1[48];      // (color palette, for older not 256 col vers.)
  49. byte PCX_reserved;          // reserved byte
  50. byte PCX_color_planes;      // number of color planes
  51. word PCX_bytes_per_line;    // line buffer size
  52. word PCX_palette_type;      // grey or color palette indicator
  53. byte PCX_reserved2[58];     // reserved
  54. // end of PCX header
  55.  
  56.  
  57. byte readPCXpalette (word filename,palsegment,paloffset)
  58. /*
  59.   This procedure reads the last 769 bytes of the PCX file.
  60.   Checks if we are at the palette (cuz pcx's have the palette at the end of
  61.   file) and then reads it into memory at PALETTE
  62. */
  63. word filehandle;
  64. byte temp;
  65. {
  66. filehandle = FOPEN(0, , ,filename);   /* open file */
  67. IF(filehandle == 0)                    /* if file did not open */
  68.     return(pcx_e_nofile);
  69. CX = -1;
  70. DX = -769;
  71. BX = filehandle;
  72. AX = 0x4202;
  73. $INT 0x21
  74. IF( CARRYFLAG )
  75.     {FCLOSE( ,filehandle);  /* close the file */
  76.     return(pcx_e_noinput);}
  77.  
  78. AX = FREAD( ,filehandle,1,#temp); 
  79. IF( temp != 0xC )
  80.     {FCLOSE( ,filehandle);  /* close the file */
  81.     return(pcx_e_badheader);}
  82.  
  83. $ PUSH DS
  84. DS = palsegment;
  85. IF( FREAD( ,filehandle,768,paloffset) != 768 )
  86.     {$ POP DS
  87.     FCLOSE( ,filehandle);  /* close the file */
  88.     return(pcx_e_noinput);
  89.     }
  90. DI = paloffset;
  91. CX = 768;
  92. loop(CX)
  93.     {AL = DSBYTE[DI];   // convert the palette from
  94.     $ SHR AL,1          // 8 bits
  95.     $ SHR AL,1          // to 6 bits
  96.     DSBYTE[DI] = AL;    // and save it
  97.     DI++;
  98.     }
  99. $ POP DS
  100. FCLOSE( ,filehandle);  /* close the file */
  101. return(pcx_e_ok); 
  102. }
  103.  
  104.  
  105. byte readPCX (word filename,bufseg,bufoffset,bufsize; byte buftype)
  106. /*
  107.   Reads and checks the header of the pcx to make sure that it is a pcx file,
  108.   it then reads the data into the buffer given by bufseg:bufoffset.
  109. */
  110. word filehandle;
  111. word xcount; 
  112. word ycount;  
  113. word local_bytesperline;
  114. byte readbuf[PCXBUFSIZE];
  115. {
  116. filehandle = FOPEN(0, , ,filename);   /* open file */
  117. IF(filehandle == 0)                    /* if file did not open */
  118.     return(pcx_e_nofile);
  119.  
  120. // read the PCX file header into the header buffer
  121. IF( FREAD( ,filehandle,PCX_HEADERSIZE,#PCX_manufacturer) != PCX_HEADERSIZE )
  122.     {FCLOSE( ,filehandle);  /* close the file */
  123.     return(pcx_e_noinput);}
  124. IF( PCX_manufacturer != 0x0A )   // check the manufacturer byte
  125.     {FCLOSE( ,filehandle);  /* close the file */
  126.     return(pcx_e_badheader);}
  127. IF( PCX_version != 5 )   // check the version
  128.     {FCLOSE( ,filehandle);  /* close the file */
  129.     return(pcx_e_badheader);}
  130.  
  131. IF( PCX_bits_per_pixel != 8 )
  132.     {FCLOSE( ,filehandle);  /* close the file */
  133.     return(pcx_e_not256);}
  134.  
  135. IF( PCX_color_planes > 1 )
  136.     {FCLOSE( ,filehandle);  /* close the file */
  137.     return(pcx_e_not256);}
  138.  
  139. xcount = PCX_xmax - PCX_xmin +1;
  140. ycount = PCX_ymax - PCX_ymin +1;
  141. local_bytesperline = xcount;
  142.  
  143. AX = xcount;
  144. BX = ycount;
  145. $ MUL BX
  146. IF( DX > 0 )
  147.     {FCLOSE( ,filehandle);  /* close the file */
  148.     return(pcx_e_toobig);}
  149. IF( AX > bufsize )
  150.     {FCLOSE( ,filehandle);  /* close the file */
  151.     return(pcx_e_toobig);}
  152.  
  153. $ CLD              // clear the direction flag
  154.  
  155. ES = bufseg;
  156. DI = bufoffset;
  157.  
  158. SI = PCXBUFSIZE;   // set input pointer to end, so data will have to be read
  159.  
  160. IF( buftype == pcx_cut )  // if CUT buffer format, store x and y sizes first
  161.     {AX = xcount;
  162.     $ STOSW
  163.     AX = ycount;
  164.     $ STOSW
  165.     }
  166.  
  167. do {
  168.     xcount = local_bytesperline;  // reset the image width
  169.  
  170.     do {
  171.         IF( SI == PCXBUFSIZE )
  172.             {$ PUSH DI
  173.             $ PUSH ES
  174.             AX = FREAD( ,filehandle,PCXBUFSIZE,#readbuf);  // read some data
  175.             IF( AX == 0 )
  176.                 {FCLOSE( ,filehandle);  /* close the file */
  177.                 return(pcx_e_noinput);}
  178.             SI = 0;
  179.             $ POP ES
  180.             $ POP DI
  181.             }
  182.         AL = readbuf[SI];   // get a byte to unpack
  183.         SI++;
  184.  
  185.         IF( AL >= 0xC0 )         // if byte is repeater code
  186.             {                    // yes,
  187.             AL &= 0x3F;   
  188.             CX = 0;
  189.             CL = AL;             // get count into cx
  190.             xcount -= CX;   // subtract it from the width counter
  191.  
  192.             IF( SI == PCXBUFSIZE )
  193.                 {$ PUSH DI
  194.                 $ PUSH ES
  195.                 $ PUSH CX
  196.                 AX = FREAD( ,filehandle,PCXBUFSIZE,#readbuf);  // read some data
  197.                 IF( AX == 0 )
  198.                     {FCLOSE( ,filehandle);  /* close the file */
  199.                     return(pcx_e_noinput);}
  200.                 SI = 0;
  201.                 $ POP CX
  202.                 $ POP ES
  203.                 $ POP DI
  204.                 }
  205.             AL = readbuf[SI];   // get the byte pattern
  206.             SI++;
  207.  
  208.             $ REPNE
  209.             $ STOSB             // write the byte
  210.             }
  211.         ELSE{              // not a pattern call soo...
  212.             xcount--;      // decrement our counter
  213.             $ STOSB        // write the byte to the screen
  214.             }
  215.         } while( xcount > 0 );
  216.  
  217.     ycount--;
  218.     } while( ycount > 0 );
  219.  
  220. FCLOSE( ,filehandle);  /* close the file */
  221.  
  222. return(pcx_e_ok);
  223. }
  224.  
  225.  
  226. byte savePCX (word filename,bufseg,bufoffset,xsize,ysize,palseg,paloffset)
  227. /*
  228.   Saves the buffer and palette in a valid PCX file.
  229.   It works, but the compression could be done a little better.  Some how...
  230. */
  231. word filehandle;
  232. word xcount; 
  233. byte writebuf[PCXBUFSIZE];
  234. byte currentbyte;
  235. byte currentcount;
  236. {
  237. AH = 0x3C;
  238. CX = 0;
  239. DX = filename;
  240. $ INT 0x21     /* create file */
  241. IF( CARRYFLAG )  // unable to create
  242.     return(pcx_e_nofile);
  243. filehandle = AX;
  244.  
  245. ES = DS;
  246. DI = #PCX_manufacturer;
  247. CX = PCX_HEADERSIZE;
  248. AL = 0;
  249. $ REPZ
  250. $ STOSB   // zero the entire PCX header
  251.  
  252. PCX_manufacturer = 0xA;
  253. PCX_version = 5;
  254. PCX_bits_per_pixel = 8;
  255. PCX_color_planes = 1;
  256. PCX_xmax = xsize-1;
  257. PCX_ymax = ysize-1;
  258. PCX_hres = 320;  
  259. PCX_vres = 200;  
  260. PCX_encoding = 1;
  261. PCX_bytes_per_line = xsize;
  262. PCX_palette_type = 1;      // grey or color palette indicator
  263.  
  264.  
  265. // write the PCX header to the file
  266. IF( FWRITE( ,filehandle,PCX_HEADERSIZE,#PCX_manufacturer) != PCX_HEADERSIZE )
  267.     {FCLOSE( ,filehandle);  /* close the file */
  268.     return(pcx_e_nooutput);}
  269.  
  270. $ CLD              // clear the direction flag
  271.  
  272. ES = bufseg;
  273. SI = bufoffset;
  274.  
  275. DI = 0;   // set input pointer to end, so data will have to be read
  276.  
  277. do {
  278.     xcount = xsize;  // reset the image width
  279.  
  280.     do {
  281.         currentcount = 1;
  282.         currentbyte = ESBYTE[SI];
  283.         SI++;
  284.  
  285.         do {
  286.             DL = FALSE;
  287.             IF( ESBYTE[SI] == currentbyte )
  288.                 IF( xcount > 1 )
  289.                     IF( currentcount < 63 )
  290.                         {xcount--;
  291.                         currentcount++;
  292.                         SI++;
  293.                         DL = TRUE;
  294.                         }
  295.             } while( DL == TRUE );
  296.  
  297.         IF( DI == PCXBUFSIZE )
  298.             {$ PUSH SI
  299.             $ PUSH ES
  300.             IF( FWRITE( ,filehandle,PCXBUFSIZE,#writebuf) != PCXBUFSIZE )
  301.                 {FCLOSE( ,filehandle);  /* close the file */
  302.                 return(pcx_e_noinput);}
  303.             $ POP ES
  304.             $ POP SI
  305.             DI = 0;
  306.             }
  307.         IF( currentcount > 1 )
  308.             {writebuf[DI] = 0xC0 + currentcount;
  309.             DI++;
  310.             }
  311.         ELSE IF( currentbyte >= 0xC0 )
  312.             {writebuf[DI] = 0xC0 + currentcount;
  313.             DI++;
  314.             }
  315.  
  316.         IF( DI == PCXBUFSIZE )
  317.             {$ PUSH SI
  318.             $ PUSH ES
  319.             IF( FWRITE( ,filehandle,PCXBUFSIZE,#writebuf) != PCXBUFSIZE )
  320.                 {FCLOSE( ,filehandle);  /* close the file */
  321.                 return(pcx_e_noinput);}
  322.             $ POP ES
  323.             $ POP SI
  324.             DI = 0;
  325.             }
  326.         writebuf[DI] = currentbyte;
  327.         DI++;
  328.  
  329.         xcount--;      // decrement our counter
  330.         } while( xcount > 0 );
  331.  
  332.     ysize--;
  333.     } while( ysize > 0 );
  334.  
  335. IF( DI > 0 )
  336.     {IF( FWRITE( ,filehandle,DI,#writebuf) == 0 )
  337.         {FCLOSE( ,filehandle);  /* close the file */
  338.         return(pcx_e_noinput);}
  339.     }
  340.  
  341. /*** We must now save the palette ***/
  342.  
  343. writebuf[0] = 0xC;      // palette notifier byte
  344.  
  345. ES = palseg;
  346. SI = paloffset;
  347.  
  348. DI = 0;
  349. do {AL = ESBYTE[SI];      // convert the palette from
  350.     $ SHL AL,1            // 6 bits
  351.     $ SHL AL,1            // to 8 bits
  352.     writebuf[1+DI] = AL;  // and save it
  353.     DI++;
  354.     SI++;
  355.     } while( DI < 768 );
  356.  
  357. IF( FWRITE( ,filehandle,769,#writebuf) != 769 )
  358.     {FCLOSE( ,filehandle);  /* close the file */
  359.     return(pcx_e_nooutput);
  360.     }
  361. FCLOSE( ,filehandle);  /* close the file */
  362.  
  363. return(pcx_e_ok);
  364. }
  365.  
  366. /* end of PCX.H-- */